package com.example.lin.util;

import com.example.lin.vo.EddHolidayVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * EddTimeUtils类提供了与日期处理相关的一系列工具方法，特别适用于处理与edd业务相关的日期计算。
 */
public class EddTimeUtils {
    // 日志对象，用于记录日志信息
    private static final Logger logger = LoggerFactory.getLogger(EddTimeUtils.class);

    // 定义了一系列日期和时间的格式常量，用于日期时间的解析和格式化
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String DATE_FORMAT_MM = "yyyy-MM";
    public static final String DATE_FORMAT_HH_MM = "yyyy-MM-dd HH:mm";
    public static final String DATE_TIME_FORMAT_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DAYTIME_END = "23:59:59.999";
    public static final String DAYTIME_START = "00:00:00.000";
    public static final String DATE_HH_MM = "HH:mm";
    public static final String DATE_HH_MM_SS = "HH:mm:ss";
    public static final String DATE_HH_MM_SS_SSS = "HH:mm:ss.SSS";
    public static final String DC_DATE_FORMAT = "yyyy/MM/dd";
    public static final String DC_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss";

    // 定义了一组常用的日期时间格式，便于在解析或格式化日期时使用
    private static final String[] FORMATS = {DATE_FORMAT, DATE_FORMAT_HH_MM,
            DATE_TIME_FORMAT, DATE_HH_MM, DATE_HH_MM_SS, DATE_HH_MM_SS_SSS, DATE_FORMAT_MM,
            DATE_TIME_FORMAT_SSS, DC_DATE_FORMAT, DC_TIME_FORMAT};

    /**
     * 根据给定的日期和天数范围，计算查询日期的起始和结束时间。
     *
     * @param date     基准日期
     * @param startDay 开始天数偏移量
     * @param endDay   结束天数偏移量
     * @return 包含起始和结束时间的映射
     */
    public static Map<Integer, Date> getQueryDateMap(Date date, Integer startDay, Integer endDay) {
        Date resultDateStart = addDayToDate(date, startDay);
        Date resultDateEnd = resultDateStart;
        if (Objects.nonNull(endDay)) {
            resultDateEnd = addDayToDate(date, endDay);
        }
        // 时间开始时间
        Date currentStartTime = getStartDatetime(resultDateStart);
        // 时间结束时间
        Date currentEndTime = getEndDatetime(resultDateEnd);
        Map<Integer, Date> dateMap = new HashMap<>();
        dateMap.put(1, currentStartTime);
        dateMap.put(2, currentEndTime);
        return dateMap;
    }

    /**
     * 将给定日期增加指定天数。
     *
     * @param date 原始日期
     * @param day  增加的天数
     * @return 增加天数后的日期
     */
    public static Date addDayToDate(Date date, int day) {
        return new Date(date.getTime() + 1000L * 24 * 60 * 60 * day);
    }

    /**
     * 计算工作日，不包含法定假期
     *
     * @param src     日期(源)
     * @param adddays 要加的天数
     * @return 计算后的工作日
     */
    public static Calendar addDateByWorkDay(Calendar src, int adddays) {
        boolean holidayFlag;
        for (int i = 0; i < adddays; i++) {
            //把源日期加一天
            src.add(Calendar.DAY_OF_MONTH, 1);
            //先检查是否是周六周日(有些国家是周五周六)
            holidayFlag = src.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || src.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
            if (holidayFlag) {
                i--;
            }
        }
        return src;
    }

    /**
     * 计算假期总天数
     *
     * @param holidayList            假期列表
     * @param startTime              开始时间
     * @param endTime                结束时间
     * @param timeZoneOffsetInMillis 时区偏移量（毫秒）
     * @return 假期总天数
     */
    public static Long calculateTotalHolidays(List<EddHolidayVO> holidayList, Date startTime, Date endTime, long timeZoneOffsetInMillis) {
        long totalHolidays = 0;

        for (EddHolidayVO holiday : holidayList) {
            Date holidayStartDate = convertToTimeZone(holiday.getStartDate(), timeZoneOffsetInMillis);
            Date holidayEndDate = convertToTimeZone(holiday.getEndDate(), timeZoneOffsetInMillis);

            if (isHolidayInRange(holidayStartDate, holidayEndDate, startTime, endTime)) {
                Long timeDiff = getTimeDiff(holiday.getStartDate(), holiday.getEndDate());
                totalHolidays += timeDiff > 0 ? timeDiff + 1 : 0;
            }
        }

        return totalHolidays;
    }

    /**
     * 返回两个时间的相差天数
     *
     * @param startTime 对比的开始时间
     * @param endTime   对比的结束时间
     * @return 相差天数
     */
    public static Long getTimeDiff(Date startTime, Date endTime) {
        Long days = 0L;
//        //判断是否周六、周日 如果是周六日跳过
//        Calendar startCal = Calendar.getInstance();
//        startCal.setTime(startTime);
//        int startDayOfWeek = startCal.get(Calendar.DAY_OF_WEEK);
//
//        Calendar endCal = Calendar.getInstance();
//        endCal.setTime(endTime);
//        int endDayOfWeek = endCal.get(Calendar.DAY_OF_WEEK);
//
//        // 使用常量提高可读性
//        if (startDayOfWeek == Calendar.SATURDAY || startDayOfWeek == Calendar.SUNDAY ||
//                endDayOfWeek == Calendar.SATURDAY || endDayOfWeek == Calendar.SUNDAY) {
//            return days;
//        }

        Calendar c = Calendar.getInstance();
        c.setTime(startTime);
        long l_s = c.getTimeInMillis();
        c.setTime(endTime);
        long l_e = c.getTimeInMillis();
        days = (l_e - l_s) / 86400000;
        return days;
    }

    /**
     * 判断假期是否在指定范围内
     *
     * @param holidayStartDate 假期开始日期
     * @param holidayEndDate   假期结束日期
     * @param startTime        指定范围的开始时间
     * @param endTime          指定范围的结束时间
     * @return 如果假期在指定范围内则返回true，否则返回false
     */
    public static boolean isHolidayInRange(Date holidayStartDate, Date holidayEndDate, Date startTime, Date endTime) {
        return (holidayStartDate.after(startTime) && holidayStartDate.before(endTime))
                || (holidayEndDate.after(startTime) && holidayEndDate.before(endTime))
                || (holidayStartDate.equals(startTime) || holidayStartDate.equals(endTime))
                || (holidayEndDate.equals(startTime) || holidayEndDate.equals(endTime));
    }

    /**
     * 转换为东八区时间
     *
     * @param date                   原始日期
     * @param timeZoneOffsetInMillis 时区偏移量（毫秒）
     * @return 转换后的日期
     */
    public static Date convertToTimeZone(Date date, long timeZoneOffsetInMillis) {
        if (date == null) {
            return null;
        }
        return new Date(date.getTime() + timeZoneOffsetInMillis);
    }

    /**
     * 将字符串日期转换为Date对象。
     *
     * @param str 日期字符串
     * @return 转换后的Date对象，如果无法解析则返回null
     */
    public static Date convert(String str) {
        if (str != null && str.length() > 0) {
            if (str.length() > 10 && str.charAt(10) == 'T') {
                str = str.replace('T', ' '); // 去掉json-lib加的T字母
            }
            for (String format : FORMATS) {
                if (str.length() == format.length()) {
                    try {
                        return new SimpleDateFormat(format).parse(str);
                    } catch (ParseException e) {
                        if (logger.isWarnEnabled()) {
                            logger.warn(e.getMessage());
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * 将Date对象格式化为字符串日期。
     *
     * @param date       日期对象
     * @param dateFormat 日期格式
     * @return 格式化后的日期字符串
     */
    public static String convert(Date date, String dateFormat) {
        if (date == null) {
            return null;
        }

        if (null == dateFormat) {
            dateFormat = DATE_TIME_FORMAT;
        }

        return new SimpleDateFormat(dateFormat).format(date);
    }

    /**
     * 使用默认格式将Date对象格式化为字符串日期。
     *
     * @param date 日期对象
     * @return 格式化后的日期字符串
     */
    public static String convert(Date date) {
        return convert(date, DATE_TIME_FORMAT);
    }

    /**
     * 将String对象格式化为字符串日期。
     *
     * @param date       日期对象
     * @param dateFormat 日期格式
     * @return 格式化后的日期字符串
     */
    public static Date convert(String date, String dateFormat) {
        try {
            if (date == null) {
                return null;
            }
            if (null == dateFormat) {
                dateFormat = DATE_TIME_FORMAT;
            }
            return new SimpleDateFormat(dateFormat).parse(date);
        } catch (Exception e) {
            logger.error("日期转换异常", e);
            return null;
        }
    }

    public static Date strToDate(String dateStr, String dateFormat) {
        SimpleDateFormat formatDate = new SimpleDateFormat(dateFormat);
        Date date = null;
        try {
            date = formatDate.parse(dateStr);
        } catch (Exception e) {

        }
        return date;
    }

    /**
     * 返回该天从00:00:00开始的日期
     *
     * @param date 原始日期
     * @return 该天的开始时间
     */
    public static Date getStartDatetime(Date date) {
        String thisdate = convert(date, DATE_FORMAT);
        return convert(thisdate + " " + DAYTIME_START);
    }

    /**
     * 返回该天到23:59:59结束的日期
     *
     * @param date 原始日期
     * @return 该天的结束时间
     */
    public static Date getEndDatetime(Date date) {
        String thisdate = convert(date, DATE_FORMAT);
        return convert(thisdate + " " + DAYTIME_END);
    }

    /**
     * 当EDD 配置 目的国家为ALL就是空的时候  取节假日的时区 截取前面的数字当时差 进行匹配节假日
     *
     * @param timeZone 节假日时区
     * @return 截取前面的数字当时差
     */
    public static Integer getTimeZone(String timeZone) {
        //默认0 时差
        Integer timeDifference = 0;
        try {
            String plusOrMinus = timeZone.substring(0, 1);
            String replacementTimeZone = timeZone.replace("+", "").replace("-", "");
            if (!StringUtils.isEmpty(replacementTimeZone) && replacementTimeZone.length() >= 2) {
                String integerTimeZone = replacementTimeZone.substring(0, 2).replace(":", "");
                if (plusOrMinus.equals("-") || plusOrMinus.equals("+")) {
                    timeDifference = Integer.valueOf(plusOrMinus + integerTimeZone);
                } else {
                    timeDifference = Integer.valueOf(integerTimeZone);
                }
            }
        } catch (Exception e) {
            timeDifference = 0;
            logger.warn("EDD时区解析获取时差失败:" + e);
        }
        return timeDifference;
    }


    public static void main(String[] args) {
        Date estimatedDeliveryDate = EddTimeUtils.convert("2025-11-01 00:00:00", EddTimeUtils.DATE_TIME_FORMAT);


        Calendar instance = Calendar.getInstance();
        instance.setTime(estimatedDeliveryDate);

        int slaAging = 2;

        // 计算初始结果日期
        Date resultDate = EddTimeUtils.addDateByWorkDay(instance, slaAging).getTime();

        // 定义时间范围
        Date startTime = EddTimeUtils.getStartDatetime(estimatedDeliveryDate);
        Date endTime = EddTimeUtils.getEndDatetime(resultDate);

        System.out.println("startTime ==》" + EddTimeUtils.convert(startTime, EddTimeUtils.DATE_TIME_FORMAT));
        System.out.println("endTime ==》" + EddTimeUtils.convert(endTime, EddTimeUtils.DATE_TIME_FORMAT));


        //时差  用节假日
        //Integer timeDifference = getTimeZone("-5:00:00");
        //用配置的
        Integer timeDifference = 7;
        long timeZoneOffsetInMillis = timeDifference * 60 * 60 * 1000;


        //System.out.println("timeZoneOffsetInMillis==>"+timeZoneOffsetInMillis);


        Date holiday = EddTimeUtils.convert("2025-11-01", EddTimeUtils.DATE_FORMAT);
        //Date holidayEnd = EddTimeUtils.convert("2025-11-01", EddTimeUtils.DATE_FORMAT);
        Date holidayStartDate = convertToTimeZone(EddTimeUtils.getStartDatetime(holiday), timeZoneOffsetInMillis);
        Date holidayEndDate = convertToTimeZone(EddTimeUtils.getEndDatetime(holiday), timeZoneOffsetInMillis);


        System.out.println("holidayStartDate===>" + EddTimeUtils.convert(holidayStartDate, EddTimeUtils.DATE_TIME_FORMAT));
        System.out.println("holidayEndDate===>" + EddTimeUtils.convert(holidayEndDate, EddTimeUtils.DATE_TIME_FORMAT));


        Long totalHolidays = 0L;
        if (isHolidayInRange(holidayStartDate, holidayEndDate, startTime, endTime)) {
            Long timeDiff = EddTimeUtils.getTimeDiff(holidayStartDate, holidayEndDate);
            totalHolidays += timeDiff > 0 ? timeDiff + 1 : 0;
        }
        System.out.println("totalHolidays===>" + totalHolidays);

        // 累加假期天数
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(resultDate);
        resultDate = EddTimeUtils.addDateByWorkDay(calendar, totalHolidays.intValue()).getTime();

        System.out.println("结果:" + EddTimeUtils.convert(resultDate, EddTimeUtils.DATE_TIME_FORMAT));

    }
}
